package thread;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @Author fallrain
 * @Description abc三个线程按照顺序执行十次:如何保证线程的顺序执行?
 * @Date 2022/2/11 9:58
 * @Version 1.0
 */
public class FIFOThreadExample {

    //信号量
    static volatile int ticket = 1;
    //线程休眠时间
    public final static int SLEEP_TIME = 1;

    public static void foo(String name) {
        System.out.println(name);
    }

    public static void foo(int name){
        //因为线程的执行顺序是不可预期的，因此需要每个线程自旋
        while (true){
            if(ticket == name){
                try {
                    Thread.sleep(SLEEP_TIME);
                    //每个线程循环打印三次
                    for (int i = 0; i < 3; i++) {
                        System.out.println(name + "" + i);
                    }
                }catch (InterruptedException e){
                    e.printStackTrace();
                }
                //信号量变更
                ticket = name%3+1;
                return;
            }
        }
    }

    public static void main(String[] args) throws InterruptedException{
        Thread thread1 = new Thread(() -> foo("A"));
        Thread thread2 = new Thread(() -> foo("B"));
        Thread thread3 = new Thread(() -> foo("C"));

        //1. 使用Thread.join()实现
//        for (int i = 0; i < 10; i++) {
//            thread1.start();
//            thread1.join();
//            thread2.start();
//            thread2.join();
//            thread3.start();
//        }
        //2. 使用单线程线程池来实现
//        ExecutorService executorService = Executors.newSingleThreadExecutor();
//        for (int i = 0; i < 10; i++) {
//            executorService.submit(thread1);
//            executorService.submit(thread2);
//            executorService.submit(thread3);
//        }
//        executorService.shutdown();
        //3. 使用volatile关键字修饰的信号量实现
        for (int i = 0; i < 10; i++) {
            Thread.sleep(SLEEP_TIME);
            new Thread(() -> foo(1)).start();
            new Thread(() -> foo(2)).start();
            new Thread(() -> foo(3)).start();
        }

    }
}
